/*
 * 础石AUTOSAR CP操作系统 -- GetSpinlock接口实现文件
 *
 * Copyright (C) 2022 国科础石(重庆)软件有限公司
 *
 * 作者: Zicheng Hu <huzicheng@kernelsoft.com>
 *       Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <autosar/internal.h>

VAR(struct autosar_smp_lock, AUTOMATIC) autosar_spin_locks[AUTOSAR_NR_SPIN_LOCK];
VAR(SpinlockIdType, AUTOMATIC) autosar_spin_locks_order[AUTOSAR_NR_SPIN_LOCK];

FUNC(StatusType, OS_CODE) GetSpinlock(
	VAR(SpinlockIdType, AUTOMATIC) SpinlockId)
{
	VAR(CoreIdType, AUTOMATIC) core_id = GetCoreID();
	VAR(SpinlockIdType, AUTOMATIC) spin_lock_index = AUTOSAR_NR_SPIN_LOCK;
	VAR(SpinlockIdType, AUTOMATIC) i;

#if defined(EXTENDED_STATUS)
	/*
	* [SWS_Os_00689] 如果SpinlockID代表的spinlock不存在，则返回E_OS_ID.
	*
	*/
	if (SpinlockId >= AUTOSAR_NR_SPIN_LOCK) {
		return E_OS_ID;
	}
	/**
	 * [SWS_Os_00690] 如果SpinlockId所指定的spin_lock已经被同一个cpu上的程序占有了，则返回E_OS_INTERFERENCE_DEADLOCK。
	 */
	if (autosar_spin_locks[SpinlockId].owner_core_id == core_id) {
		return E_OS_INTERFERENCE_DEADLOCK;
	}

	/**
	 * [SWS_Os_00691] 如果获取spin_lock的顺序与配置顺序不相同，则返回E_OS_NESTING_DEADLOCK。
	 */
	for (i = 0; i < AUTOSAR_NR_SPIN_LOCK - 1; i++) {
		if (autosar_spin_locks_order[i] == SpinlockId) {
			spin_lock_index = i;
			break;
		}
	}
	for (i = AUTOSAR_NR_SPIN_LOCK - 1; i > spin_lock_index;
		i--) {
		VAR(SpinlockIdType, AUTOMATIC) index = autosar_spin_locks_order[i];
		if (!smp_lock_is_locked(&autosar_spin_locks[index].smp_lock)) {
			continue;
		}
		return E_OS_NESTING_DEADLOCK;
	}
#endif

	SuspendAllInterrupts();
	smp_lock(&autosar_spin_locks[SpinlockId].smp_lock);
	autosar_spin_locks[SpinlockId].owner_core_id = core_id;
#if defined(AUTOSAR_OS_APPLICATION)
	autosar_spin_locks[SpinlockId].owner_app_id = GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	/**
	 * [SWS_Os_00688] 如果顺利获取spin_lock，则返回E_OK.
	 */
	return E_OK;
}


FUNC(StatusType, OS_CODE) ReleaseSpinlock(
	VAR(SpinlockIdType, AUTOMATIC) SpinlockId)
{
	VAR(SpinlockIdType, AUTOMATIC) spin_lock_index = AUTOSAR_NR_SPIN_LOCK;
	VAR(SpinlockIdType, AUTOMATIC) i;

#if defined(EXTENDED_STATUS)
	/*
	* [SWS_Os_00698] 如果SpinlockID代表的spinlock不存在，则返回E_OS_ID.
	*/
	if (SpinlockId >= AUTOSAR_NR_SPIN_LOCK) {
		return E_OS_ID;
	}

	/**
	 * [SWS_Os_00699] 如果SpinlockId所指定的spin_lock并没有被占有，则返回E_OS_STATE.
	 */
	if (!smp_lock_is_locked(&autosar_spin_locks[SpinlockId].smp_lock)) {
		return E_OS_STATE;
	}

	/**
	 * [SWS_Os_00701] 如果在释放 SpinlockId代表的spin_lock之前，还需要释放另外的spin_lock，则返回 E_OS_NOFUNC
	 */
	for (i = 0; i < AUTOSAR_NR_SPIN_LOCK - 1; i++) {
		if (autosar_spin_locks_order[i] == SpinlockId) {
			spin_lock_index = i;
			break;
		}
	}
	for (i = AUTOSAR_NR_SPIN_LOCK - 1; i > spin_lock_index;
		i--) {
		VAR(SpinlockIdType, AUTOMATIC) index = autosar_spin_locks_order[i];
		if (!smp_lock_is_locked(&autosar_spin_locks[index].smp_lock)) {
			continue;
		}
		return E_OS_NOFUNC;
	}
#endif

	autosar_spin_locks[SpinlockId].owner_core_id = MAX_CPUS;
	smp_unlock(&autosar_spin_locks[SpinlockId].smp_lock);
	ResumeAllInterrupts();

	/**
	 * [SWS_Os_00697] 如果没遇到问题，则返回E_OK.
	 */
	return E_OK;
}

FUNC(StatusType, OS_CODE) TryToGetSpinlock(
	VAR(SpinlockIdType, AUTOMATIC) SpinlockId,
	P2VAR(TryToGetSpinlockType, AUTOMATIC, OS_APPL_DATA) Success)
{
	VAR(CoreIdType, AUTOMATIC) core_id = GetCoreID();
	VAR(SpinlockIdType, AUTOMATIC) i;

#if defined(EXTENDED_STATUS)
	VAR(SpinlockIdType, AUTOMATIC) spin_lock_index = AUTOSAR_NR_SPIN_LOCK;

	/**
	 * [SWS_Os_00707] 如果SpinlockId对应的spinlock不存在，则返回E_OS_ID.
	 */
	if (SpinlockId >= AUTOSAR_NR_SPIN_LOCK) {
		return E_OS_ID;
	}

	/**
	 * [SWS_Os_00708] 如果SpinlockId所指定的spin_lock已经被同一个cpu上的程序占有了，则返回E_OS_INTERFERENCE_DEADLOCK。
	 */
	if (autosar_spin_locks[SpinlockId].owner_core_id == core_id) {
		return E_OS_INTERFERENCE_DEADLOCK;
	}

	/**
	 * [SWS_Os_00709] 如果获取spin_lock的顺序与配置顺序不相同，则返回E_OS_NESTING_DEADLOCK。
	 */
	for (i = 0; i < AUTOSAR_NR_SPIN_LOCK - 1; i++) {
		if (autosar_spin_locks_order[i] == SpinlockId) {
			spin_lock_index = i;
			break;
		}
	}
	for (i = AUTOSAR_NR_SPIN_LOCK - 1; i > spin_lock_index;
		i--) {
		VAR(SpinlockIdType, AUTOMATIC) index = autosar_spin_locks_order[i];
		if (!smp_lock_is_locked(&autosar_spin_locks[index].smp_lock)) {
			continue;
		}
		return E_OS_NESTING_DEADLOCK;
	}
#endif
	/**
	 * [SWS_Os_00705] 如果获得了锁，则*Success 为 TRYTOGETSPINLOCK_SUCCESS， 如果没能获得锁，则*Success 为 TRYTOGETSPINLOCK_NOSUCCESS
	 * 无论获取与否，return E_OK.
	 */
	SuspendAllInterrupts();

	if (smp_trylock(&autosar_spin_locks[SpinlockId].smp_lock)) {
		*Success = TRYTOGETSPINLOCK_SUCCESS;
		autosar_spin_locks[SpinlockId].owner_core_id = core_id;
	#if defined(AUTOSAR_OS_APPLICATION)
		autosar_spin_locks[SpinlockId].owner_app_id = GetApplicationID();
	#endif /* defined(AUTOSAR_OS_APPLICATION) */
	} else {
		*Success = TRYTOGETSPINLOCK_NOSUCCESS;
		ResumeAllInterrupts();
	}

	/**
	 * [SWS_Os_00688] 如果顺利获取spin_lock，则返回E_OK.
	 */
	return E_OK;
}

FUNC(void, OS_CODE) autosar_init_smp_spin_lock(void)
{
	VAR(SpinlockIdType, AUTOMATIC) i;
	for (i = 0; i < AUTOSAR_NR_SPIN_LOCK; i++) {
		smp_lock_init(&autosar_spin_locks[i].smp_lock);
		autosar_spin_locks[i].owner_core_id = MAX_CPUS;
		memset(autosar_spin_locks[i].accessable_application_id, 0,
			sizeof(autosar_spin_locks[i].accessable_application_id));
		autosar_spin_locks_order[i] = i;
	}
	smp_lock_init(&activate_task_async_lock);
	smp_lock_init(&set_event_async_lock);
}